package com.gitee.magic.framework.base.rest;

import java.io.IOException;
import java.net.HttpURLConnection;
import java.util.HashMap;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.CollectionUtils;

import com.gitee.magic.core.exception.ApplicationException;
import com.gitee.magic.framework.base.constant.Config;
import com.gitee.magic.framework.head.utils.IoUtils;

/**
 * @author start
 */
public class HttpWrapper {

	private static final Logger LOGGER = LoggerFactory.getLogger(HttpWrapper.class);

	public static final String AUTHORIZATION="Authorization";
	public static final String ACCEPT="accept";
	public static final String CONTENTTYPE="Content-Type";
	public static final String CONTENTTYPE_GZIP="application/gzip";
	public static final String CONTENTTYPE_JSON="application/json";
	public static final String CONTENTTYPE_TEXT="application/text";
	public static final String CONTENTTYPE_SERIALIZE="application/serialize";
	public static final String CONTENTTYPE_URLENCODE="application/x-www-form-urlencoded";
	
	public HttpWrapper() {
	}
	
	public String start(String requestUrl,Map<String,Object> params) {
		return start(requestUrl,RequestMethodEnum.POST,params);
	}
	
	public String start(String requestUrl,RequestMethodEnum method,Map<String,Object> params) {
		return start(requestUrl,method,new HashMap<>(0),new HashMap<>(0),params);
	}
	
	public String start(String requestUrl,RequestMethodEnum method,Map<String,String> headers,Map<String,Object> params) {
		return start(requestUrl,method,new HashMap<>(0),headers,params);
	}
	
	public String start(String requestUrl,RequestMethodEnum method,Map<String,String> urlParams,Map<String,String> headers,Map<String,Object> params) {
		HttpRequest request=new HttpRequest(requestUrl,method);
		request.setUrlParams(urlParams);
		request.setHeaders(headers);
		request.setJsonBodyContent(params);
		return start(request);
	}
	
	/**
	 * 创建连接对象可配置相关参数
	 * @param request
	 * @return
	 */
	public HttpURLConnection createConnect(HttpRequest request) {
		HttpURLConnection connection=null;
		if(!CollectionUtils.isEmpty(request.getHeaders())) {
			if (LOGGER.isInfoEnabled()) {
				LOGGER.info("url:{}_{} header:{}", request.getRequestUrl(),request.getRequestMethod().name(),request.getHeaders());
			}
		}
		if(request.getRequestMethod()==RequestMethodEnum.GET) {
			connection=HttpClient.createGetHttpConnection(request.getRequestUrl(),request.getHeaders());
		}else if(request.getRequestMethod()==RequestMethodEnum.POST||
				request.getRequestMethod()==RequestMethodEnum.PUT||
				request.getRequestMethod()==RequestMethodEnum.DELETE){
			connection=HttpClient.createDefaultHttpConnection(request.getRequestUrl(),request.getRequestMethod().name(),request.getHeaders());
		}else {
			//
		}
		return connection;
	}
	
	public HttpURLConnection requestConnect(HttpRequest request) {
		HttpURLConnection connection=createConnect(request);
		if(request.getBodyContent()!=null) {
			if (LOGGER.isInfoEnabled()) {
				LOGGER.info("url:{}_{} body:{}", request.getRequestUrl(),request.getRequestMethod().name(),request.getBodyContent());
			}
			HttpClient.setRequestBody(connection, request.getBodyContent(), Config.getEncoding());
		}
		return connection;
	}
	
	public String start(HttpRequest request) {
		HttpURLConnection connection=requestConnect(request);
		return start(request,connection);
	}
	
	public String start(HttpRequest request,HttpURLConnection connection) {
		long s=System.currentTimeMillis();
		byte[] bytes=startToBytes(request,connection);
		long ends=System.currentTimeMillis()-s;
		String responseData=null;
		try {
			responseData = new String(bytes, Config.getEncoding());
		} catch (IOException e) {
			throw new ApplicationException(e);
		}
		if (LOGGER.isInfoEnabled()) {
			LOGGER.info("url:{}_{} response:{} ({}ms)", request.getRequestUrl(),request.getRequestMethod().name(),responseData,ends);
		}
		return responseData;
	}
	
	public byte[] startToBytes(HttpRequest request,HttpURLConnection connection) {
		int code;
		try {
			code = connection.getResponseCode();
		} catch (IOException e) {
			throw new ApplicationException(e);
		}
		int startCode=200;
		int endCode=300;
		if (!(code>=startCode&&code<endCode)) {
			byte[] bytes=IoUtils.inputStreamConvertBytes(connection.getErrorStream(),connection.getContentLength());
			int badCode=400;
			if(code==badCode) {
				return bytes;
			}
			String content=new String(bytes);
			throw new ApplicationException(String.format("URL:%s,ResponseCode：%s,ResponseBody:%s", request.getRequestUrl(), code,content));
		}
		try {
			return IoUtils.inputStreamConvertBytes(connection.getInputStream(),
					connection.getContentLength());
		} catch (IOException e) {
			throw new ApplicationException(e);
		}
	}
	
}
